package ms.jacrim.pddl.viewer;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Calendar;

import ms.jacrim.pddl.PddlSolution;
import ms.jacrim.pddl.SolutionEvaluator;
import ms.jacrim.pddl.SolutionEvaluatorManager;
import ms.jacrim.pddl.PddlSolution.PddlActor;
import ms.jacrim.pddl.PddlSolution.PddlGoal;
import ms.spm.IAppContext;
import ms.utils.XmlFile;

import org.eclipse.nebula.widgets.ganttchart.DefaultSettings;
import org.eclipse.nebula.widgets.ganttchart.GanttChart;
import org.eclipse.nebula.widgets.ganttchart.GanttComposite;
import org.eclipse.nebula.widgets.ganttchart.GanttEvent;
import org.eclipse.nebula.widgets.ganttchart.GanttSection;
import org.eclipse.nebula.widgets.ganttchart.ISettings;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;

import com.swtdesigner.SWTResourceManager;

public class SolutionViewer extends Composite {

	private Text txtSolution;
	private ViewForm vfChart;
	private GanttComposite chartComposite;
	private IAppContext context;
	private GanttChart ganttChart;
	
	public SolutionViewer(IAppContext context, Composite parent, int flags) {
		super(parent, flags);
		
		this.context = context;
		
		setLayout(new FillLayout());

		final TabFolder tabFolder = new TabFolder(this, SWT.BOTTOM);
		tabFolder.setBackground(SWTResourceManager.getColor(255, 255, 255));

		final TabItem solutionTabItem = new TabItem(tabFolder, SWT.NONE);
		solutionTabItem.setImage(SWTResourceManager.getImage(SolutionViewer.class, "cubes.png"));
		solutionTabItem.setText("Solution");

		txtSolution = new Text(tabFolder, SWT.V_SCROLL | SWT.READ_ONLY | SWT.MULTI | SWT.H_SCROLL);
		txtSolution.setTabs(4);
		txtSolution.setBackground(SWTResourceManager.getColor(255, 255, 255));
		solutionTabItem.setControl(txtSolution);
		
		final TabItem ganttChartTabItem = new TabItem(tabFolder, SWT.NONE);
		ganttChartTabItem.setImage(SWTResourceManager.getImage(SolutionViewer.class, "GanttChart.jpg"));
		ganttChartTabItem.setText("Gantt Chart");

		final Composite composite = new Composite(tabFolder, SWT.NONE);
		composite.setLayout(new FormLayout());
		composite.setBackground(SWTResourceManager.getColor(255, 255, 255));
		composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
		ganttChartTabItem.setControl(composite);

		vfChart = new ViewForm(composite, SWT.BORDER);
		final FormData fd_vfChart = new FormData();
		fd_vfChart.left = new FormAttachment(0, 5);
		fd_vfChart.right = new FormAttachment(100, -7);
		fd_vfChart.top = new FormAttachment(0, 5);
		vfChart.setLayoutData(fd_vfChart);
		
		Group eventPropertiesGroup;
		eventPropertiesGroup = new Group(composite, SWT.NONE);
		fd_vfChart.bottom = new FormAttachment(eventPropertiesGroup, -5, SWT.TOP);
		eventPropertiesGroup.setText("Event Properties");
		final FormData fd_eventPropertiesGroup = new FormData();
		fd_eventPropertiesGroup.right = new FormAttachment(100, -7);
		fd_eventPropertiesGroup.bottom = new FormAttachment(100, -8);
		fd_eventPropertiesGroup.left = new FormAttachment(0, 5);
		eventPropertiesGroup.setLayoutData(fd_eventPropertiesGroup);
		eventPropertiesGroup.setLayout(new FormLayout());
		
		createGanttChart(vfChart);
	}

	private void createGanttChart(ViewForm vfChart) {
		
		int flags = 1 << 4;
		
		ISettings setting = createGanttSetting();
		
		ganttChart = new GanttChart(vfChart, flags, setting);
		
		vfChart.setContent(ganttChart);
		
		chartComposite = ganttChart.getGanttComposite();
	}

	private ISettings createGanttSetting() {
		ISettings setting = new DefaultSettings() {
			@Override
			public Calendar getDDayRootCalendar() {
				Calendar now = Calendar.getInstance();
				return now;
			}

			@Override
			public boolean drawEventsDownToTheHourAndMinute() {
				return true;
			}

			@Override
			public int getInitialView() {
				return VIEW_DAY;
			}

			@Override
			public int getInitialZoomLevel() {
				return ZOOM_HOURS_MAX;
			}

			@Override
			public boolean enableDragAndDrop() {
				return false;
			}

			@Override
			public boolean enableResizing() {
				return false;
			}

			@Override
			public boolean lockHeaderOnVerticalScroll() {
				return true;
			}
		};
		return setting;
	}

	public void loadSolution(String solutionFile, String configFileName) throws Exception {
		PddlSolution solution = new PddlSolution();
		solution.load(solutionFile);
		
		// create gantt chart
		chartComposite.clearChart();
		
		for (PddlActor a : solution.Actors()) {
			GanttSection sec = new GanttSection(ganttChart, a.Name);
			Calendar calStart = Calendar.getInstance();
			for (PddlGoal g : a.Goals) {
				Calendar calEnd = (Calendar) calStart.clone();
				calEnd.add(Calendar.MINUTE, g.get("@duration", 40));
				GanttEvent event = new GanttEvent(ganttChart, g.Name, calStart, calEnd, 0);
				sec.addGanttEvent(event);
				calStart = calEnd;
			}
		}

		chartComposite.jumpToEarliestEvent();
		
		// generate evaluation information
		SolutionEvaluatorManager sm = new SolutionEvaluatorManager();
		sm.loadConfig(new XmlFile(configFileName));
		
		float result = sm.evaluate(solution);
		
		StringBuilder text = new StringBuilder();
		text.append(String.format("OVERRAL EVALUATION RESULT: %f \r\n", result));
		text.append("\r\n");
		text.append("Details:\r\n");
		for (SolutionEvaluator eval : sm.getEvaluators()) {
			text.append(String.format("%s : %f \tx\t %f\r\n", eval.Name(), eval.Score(), eval.getCoefficence()));
		}
		text.append("\r\n");
		text.append("SOLUTION DETAIL:\r\n");
		
		BufferedReader br = new BufferedReader(new FileReader(solutionFile));
		String line;
		while ((line = br.readLine()) != null)
			text.append(line + "\r\n");
		
		br.close();
		txtSolution.setText(text.toString());
		
	}
}
